"""
抽屉组件模块

提供了一个可以从屏幕边缘滑出的抽屉组件，支持四个方向（右、左、上、下）。
抽屉组件包含标题栏、关闭按钮和可滚动的内容区域。

修复记录:
1. 重命名冲突的width和height属性为drawer_width和drawer_height
2. 修复了遮罩层的实现，使用QGraphicsOpacityEffect实现半透明效果
3. 优化了动画效果，确保打开和关闭动画正常工作
4. 修复了关闭事件处理，防止无限循环
5. 确保抽屉组件显示在最上层
6. 优化了容器和内容区域的布局
7. 添加了详细的注释，提高代码可读性
"""
from PyQt5.QtWidgets import (QWidget, QDialog, QVBoxLayout, QHBoxLayout, 
                            QPushButton, QLabel, QGraphicsOpacityEffect, QFrame,
                            QApplication, QScrollArea)
from PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QRect, QTimer, QParallelAnimationGroup, QAbstractAnimation
from PyQt5.QtGui import QColor, QPainter, QPen, QFont
from component.theme import Theme


class Drawer(QDialog):
    """
    抽屉组件，从屏幕边缘滑出的面板
    
    用法:
        drawer = Drawer(parent, "标题", direction="right")
        # 添加内容到drawer.content_area
        drawer.show()
    """
    
    def __init__(self, parent=None, direction="right", title="", drawer_width=300, drawer_height=300, show_mask=True):
        """
        初始化抽屉组件
        
        参数:
            parent: 父窗口
            direction: 抽屉方向，可选值为 "right", "left", "top", "bottom"
            title: 抽屉标题
            drawer_width: 抽屉宽度
            drawer_height: 抽屉高度
            show_mask: 是否显示遮罩层
        """
        super().__init__(parent)
        
        # 初始化属性
        self.direction = direction
        self.title_text = title
        self.drawer_width = drawer_width
        self.drawer_height = drawer_height
        self.show_mask = show_mask
        self._animation_finished = False
        
        # 设置窗口属性
        self.setWindowTitle(title)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setModal(True)
        
        # 根据方向设置大小
        if direction in ["right", "left"]:
            self.resize(drawer_width, parent.height() if parent else drawer_height)
        else:  # top or bottom
            self.resize(parent.width() if parent else drawer_width, drawer_height)
        
        # 创建主布局
        self.main_layout = QVBoxLayout(self)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.main_layout.setSpacing(0)
        
        # 创建遮罩层
        if show_mask:
            # 设置遮罩样式
            self.setStyleSheet("background-color: rgba(0, 0, 0, 0);")
            
            # 创建遮罩效果
            self.mask_effect = QGraphicsOpacityEffect(self)
            self.mask_effect.setOpacity(0.0)  # 初始透明度为0
            self.setGraphicsEffect(self.mask_effect)
            
            # 确保遮罩层位于容器下方
            self.lower()
        
        # 创建内容容器
        self.container = QWidget(self)
        
        # 根据方向设置容器大小
        if direction in ["right", "left"]:
            self.container.resize(drawer_width, self.height())
        else:  # top or bottom
            self.container.resize(self.width(), drawer_height)
        
        # 设置容器样式
        self._apply_container_style()
        
        # 创建容器布局
        self.container_layout = QVBoxLayout(self.container)
        self.container_layout.setContentsMargins(0, 0, 0, 0)
        self.container_layout.setSpacing(0)
        
        # 创建标题栏
        if title:
            self.title_bar = QWidget()
            self.title_bar.setObjectName("drawer-title-bar")
            self.title_bar.setFixedHeight(50)
            
            title_layout = QHBoxLayout(self.title_bar)
            title_layout.setContentsMargins(16, 0, 16, 0)
            
            self.title_label = QLabel(title)
            self.title_label.setObjectName("drawer-title")
            
            self.close_button = QPushButton("×")
            self.close_button.setObjectName("drawer-close-btn")
            self.close_button.setFixedSize(24, 24)
            self.close_button.clicked.connect(self.close_with_animation)
            
            title_layout.addWidget(self.title_label)
            title_layout.addWidget(self.close_button)
            
            self.container_layout.addWidget(self.title_bar)
        
        # 创建内容区域
        self.content_area = QScrollArea()
        self.content_area.setObjectName("drawer-content")
        self.content_area.setWidgetResizable(True)
        self.content_area.setFrameShape(QFrame.NoFrame)
        
        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout(self.content_widget)
        self.content_layout.setContentsMargins(16, 16, 16, 16)
        self.content_layout.setSpacing(10)
        
        self.content_area.setWidget(self.content_widget)
        self.container_layout.addWidget(self.content_area)
        
        # 确保容器显示在最上层
        self.container.raise_()
        
        # 处理遮罩点击事件
        if show_mask:
            self.mousePressEvent = self._on_mask_clicked
    
    def _apply_container_style(self):
        """应用容器样式"""
        border_radius = ""
        
        # 根据方向设置不同的圆角
        if self.direction == "right":
            border_radius = f"border-top-left-radius: {Theme.BORDER_RADIUS_BASE}px; border-bottom-left-radius: {Theme.BORDER_RADIUS_BASE}px;"
        elif self.direction == "left":
            border_radius = f"border-top-right-radius: {Theme.BORDER_RADIUS_BASE}px; border-bottom-right-radius: {Theme.BORDER_RADIUS_BASE}px;"
        elif self.direction == "top":
            border_radius = f"border-bottom-left-radius: {Theme.BORDER_RADIUS_BASE}px; border-bottom-right-radius: {Theme.BORDER_RADIUS_BASE}px;"
        elif self.direction == "bottom":
            border_radius = f"border-top-left-radius: {Theme.BORDER_RADIUS_BASE}px; border-top-right-radius: {Theme.BORDER_RADIUS_BASE}px;"
        
        self.container.setStyleSheet(f"""
            QFrame#drawer-container {{
                background-color: {Theme.BG_COLOR};
                border: 1px solid {Theme.BORDER_LIGHT};
                {border_radius}
                z-index: 999;
            }}
            
            QWidget#drawer-title-bar {{
                background-color: {Theme.BG_COLOR};
                border-bottom: 1px solid {Theme.BORDER_LIGHTER};
            }}
            
            QLabel#drawer-title {{
                font-size: {Theme.FONT_SIZE_LARGE}px;
                font-weight: bold;
                color: {Theme.TEXT_PRIMARY};
            }}
            
            QPushButton#drawer-close-btn {{
                background-color: transparent;
                border: none;
                color: {Theme.TEXT_SECONDARY};
                font-size: 18px;
                font-weight: bold;
            }}
            
            QPushButton#drawer-close-btn:hover {{
                color: {Theme.DANGER};
            }}
            
            QScrollArea#drawer-content {{
                background-color: {Theme.BG_COLOR};
            }}
        """)
    
    def _set_initial_position(self):
        """设置初始位置（在屏幕外）"""
        parent_rect = self.parent().geometry()
        
        # 根据方向设置初始位置
        if self.direction == "right":
            self.move(parent_rect.right(), parent_rect.top())
        elif self.direction == "left":
            self.move(parent_rect.left() - self.drawer_width, parent_rect.top())
        elif self.direction == "top":
            self.move(parent_rect.left(), parent_rect.top() - self.drawer_height)
        elif self.direction == "bottom":
            self.move(parent_rect.left(), parent_rect.bottom())
    
    def showEvent(self, event):
        """显示事件"""
        super().showEvent(event)
        
        print(f"抽屉显示事件触发，方向: {self.direction}")
        print(f"父窗口大小: {self.parent().geometry()}")
        print(f"抽屉大小: 宽度={self.drawer_width}, 高度={self.drawer_height}")
        
        # 重置动画完成标志
        self._animation_finished = False
        
        # 设置初始位置
        self._set_initial_position()
        
        # 确保抽屉显示在最上层
        self.raise_()
        self.activateWindow()
        
        # 创建动画
        self.show_animation = QPropertyAnimation(self, b"geometry")
        self.show_animation.setDuration(300)
        self.show_animation.setEasingCurve(QEasingCurve.OutCubic)
        
        parent_rect = self.parent().geometry()
        
        # 根据方向设置动画
        if self.direction == "right":
            start_rect = QRect(parent_rect.right(), parent_rect.top(), self.drawer_width, self.height())
            end_rect = QRect(parent_rect.right() - self.drawer_width, parent_rect.top(), self.drawer_width, self.height())
            print(f"右侧抽屉动画: 起始={start_rect}, 结束={end_rect}")
        elif self.direction == "left":
            start_rect = QRect(parent_rect.left() - self.drawer_width, parent_rect.top(), self.drawer_width, self.height())
            end_rect = QRect(parent_rect.left(), parent_rect.top(), self.drawer_width, self.height())
            print(f"左侧抽屉动画: 起始={start_rect}, 结束={end_rect}")
        elif self.direction == "top":
            start_rect = QRect(parent_rect.left(), parent_rect.top() - self.drawer_height, parent_rect.width(), self.drawer_height)
            end_rect = QRect(parent_rect.left(), parent_rect.top(), parent_rect.width(), self.drawer_height)
            print(f"顶部抽屉动画: 起始={start_rect}, 结束={end_rect}")
        elif self.direction == "bottom":
            start_rect = QRect(parent_rect.left(), parent_rect.bottom(), parent_rect.width(), self.drawer_height)
            end_rect = QRect(parent_rect.left(), parent_rect.bottom() - self.drawer_height, parent_rect.width(), self.drawer_height)
            print(f"底部抽屉动画: 起始={start_rect}, 结束={end_rect}")
        
        self.show_animation.setStartValue(start_rect)
        self.show_animation.setEndValue(end_rect)
        
        # 遮罩动画
        if self.show_mask:
            self.mask_animation = QPropertyAnimation(self.mask_effect, b"opacity")
            self.mask_animation.setDuration(300)
            self.mask_animation.setStartValue(0.0)
            self.mask_animation.setEndValue(1.0)
            
            # 创建动画组
            self.animation_group = QParallelAnimationGroup()
            self.animation_group.addAnimation(self.show_animation)
            self.animation_group.addAnimation(self.mask_animation)
            print("启动动画组...")
            self.animation_group.start()
        else:
            print("启动显示动画...")
            self.show_animation.start()
    
    def close_with_animation(self):
        """带动画效果关闭抽屉"""
        if hasattr(self, 'close_animation') and self.close_animation.state() == QAbstractAnimation.Running:
            print("关闭动画已在运行中，忽略重复请求")
            return
            
        print("开始关闭动画...")
        
        # 创建关闭动画
        self.close_animation = QPropertyAnimation(self, b"geometry")
        self.close_animation.setDuration(300)
        self.close_animation.setEasingCurve(QEasingCurve.InCubic)
        
        current_rect = self.geometry()
        parent_rect = self.parent().geometry()
        
        # 根据方向设置动画
        if self.direction == "right":
            end_rect = QRect(parent_rect.right(), parent_rect.top(), self.drawer_width, self.height())
            print(f"右侧抽屉关闭动画: 起始={current_rect}, 结束={end_rect}")
        elif self.direction == "left":
            end_rect = QRect(parent_rect.left() - self.drawer_width, parent_rect.top(), self.drawer_width, self.height())
            print(f"左侧抽屉关闭动画: 起始={current_rect}, 结束={end_rect}")
        elif self.direction == "top":
            end_rect = QRect(parent_rect.left(), parent_rect.top() - self.drawer_height, parent_rect.width(), self.drawer_height)
            print(f"顶部抽屉关闭动画: 起始={current_rect}, 结束={end_rect}")
        elif self.direction == "bottom":
            end_rect = QRect(parent_rect.left(), parent_rect.bottom(), parent_rect.width(), self.drawer_height)
            print(f"底部抽屉关闭动画: 起始={current_rect}, 结束={end_rect}")
        
        self.close_animation.setStartValue(current_rect)
        self.close_animation.setEndValue(end_rect)
        
        # 遮罩动画
        if self.show_mask:
            self.mask_close_animation = QPropertyAnimation(self.mask_effect, b"opacity")
            self.mask_close_animation.setDuration(300)
            self.mask_close_animation.setStartValue(1.0)
            self.mask_close_animation.setEndValue(0.0)
            
            # 创建动画组
            self.close_animation_group = QParallelAnimationGroup()
            self.close_animation_group.addAnimation(self.close_animation)
            self.close_animation_group.addAnimation(self.mask_close_animation)
            self.close_animation_group.finished.connect(self._handle_close)
            print("启动关闭动画组...")
            self.close_animation_group.start()
        else:
            self.close_animation.finished.connect(self._handle_close)
            print("启动关闭动画...")
            self.close_animation.start()
            
    def _handle_close(self):
        """处理关闭动画完成后的操作"""
        print("关闭动画完成，接受关闭事件")
        self._animation_finished = True
        super().close()
    
    def mousePressEvent(self, event):
        """鼠标点击事件"""
        # 如果点击的是遮罩区域（不是容器），则关闭抽屉
        if self.show_mask and not self.container.geometry().contains(event.pos()):
            print("点击遮罩区域，关闭抽屉")
            self.close_with_animation()
        else:
            super().mousePressEvent(event)
    
    def closeEvent(self, event):
        """关闭事件处理"""
        # 如果动画已完成，则接受关闭事件
        if self._animation_finished:
            print("动画已完成，接受关闭事件")
            event.accept()
            return
            
        # 如果关闭动画正在运行，忽略重复的关闭请求
        if hasattr(self, 'close_animation') and self.close_animation.state() == QAbstractAnimation.Running:
            print("关闭动画正在运行，忽略重复的关闭请求")
            event.ignore()
            return
            
        # 否则，启动关闭动画并忽略当前关闭事件
        print("启动关闭动画并忽略当前关闭事件")
        event.ignore()
        self.close_with_animation()

    def _on_mask_clicked(self, event):
        """处理遮罩点击事件"""
        self.close_with_animation() 